/*************************************************************************
 *                                                                       *
 * This file is part of the FreeMAPs distribution.  For full copyright   *
 * information, see COPYRIGHT and COPYING.LESSER.                        *
 *                                                                       *
 * Author:           sqbang                                              *
 * Email:            sqbang@ustc.edu                                     *
 * Date:             2011.03.31                                          *
 *                                                                       *
 *************************************************************************/

#ifndef FreeMAPs_include_COMMON_info_CommonInfo_h
#define FreeMAPs_include_COMMON_info_CommonInfo_h

#include "FreeMAPsConfig.h"

//COMMON headers
#include "COMMON/base/StateIndicator.h"
//#include "COMMON/enum/Axis.h"
//#include "COMMON/enum/WarningLevelType.h"

namespace FreeMAPs
{

/**
 * @brief class CommonInfo provide common information read from file that contains controlling information
 * user may guild the problem that he want to solve by a lot of parameters, there parameters usually saved
 * in file such as setup.dat, when runing the program "$FreeMAPs -f setup.dat", the information in the setup.dat
 * will be save in a lot of info class, this class contains the common information.
 */
class CommonInfo : public StateIndicator
{
public:

    explicit
    CommonInfo(
        const std::string& object_name);

    ~CommonInfo();

public:

    /**
     * Tells how to do if there exists file with same name When
     * writing files to the disk. can take values from following:
     *  - SELF_DETERMINATION_WITH_WARNING: Show warning message and rename the file to be writing by add a suffix.
     *  - SELF_DETERMINATION_WITHOUT_WARNING: Do not show warning message and rename the file to be writing by add a suffix.
     *  - IGNORE: Similar to "WARN" without warning message.
     *  - WARN: Show warning message and overwrite the exist files and continue the program.
     *  - ERROR: Show error message and exit the program.
     * Default to "IGNORE".
     */
    //inline WarningLevelType
    //get_overwrite_exist_file_manner() const;

    /**
     * A optional parameter indicates where all needed file will be
     * located, Default is "."--the current path.
     * Note that the environment is supported. for examples, use
     * "$HOME" or "$PLAS_DIR" if it is set.
     * note that PLAS_DIR and PLAS_DIR/source can not be used as working_directory.
     */
    inline const std::string&
    get_proj_directory() const;

    inline void
    set_proj_directory(const std::string& proj_directory);

    /**
     * @brief indicate whether log on all cpus
     */
    inline bool
    do_log_all_nodes() const;

    inline bool
    do_performance_log() const;

    /**
     * @brief the base name used in the simulation. it is used for other object's name
     */
    inline const std::string&
    get_proj_name() const;

    inline void
    set_proj_name(const std::string& proj_name);

    /**
     * @brief the dimension of the probem
     */
    inline int
    get_dim() const;

    inline void
    set_dim(const int dim);

    inline int
    get_space_degree() const;

    inline void
    set_space_degree(
        const int degree);

    inline bool
    is_axial_symmetry() const;

    //inline Axis
    //get_axis_of_symmetry() const;

    inline double
    get_offset_of_axis() const;

    /**
     * @brief indicate whether do the simulation form restart
     */
    inline bool
    do_from_restart() const;

    /**
     * @brief the restart file save in the directory
     */
    inline const std::string&
    get_restart_read_directory() const;

    /**
     * @brief  do not know the meaning now.
     */
    inline int
    get_restore_number() const;

    /**
     * @brief indicate whether do write restart information
     */
    inline bool
    do_write_restart() const;

    /**
     * @brief indecate whether recording all the interval result
     * or only the last one
     */
    inline bool
    save_single_restart_file() const;

    /**
     * @brief write the restart information in this directory
     */
    inline const std::string&
    get_restart_write_directory() const;

    /**
     * @brief used in time itarator, the interval to save the restart information
     */
    inline int
    get_restart_interval() const;

    inline int
    get_max_num_time_steps() const;

    inline bool
    use_c_code_to_evaluate_function() const;

    inline bool
    stop_when_numeric_limits_reached() const;

    /**
     * when get ghost width, d_is_max_ghost_width_decided MUST be true.
     */
    inline int
    get_max_ghost_width() const;

    inline void
    update_max_ghost_width(
        const int width);

    inline bool
    is_max_ghost_width_decided() const;

    inline void
    set_max_ghost_width_decided_flag(
        const bool flag);

    inline int
    get_iteration_number() const;

    inline void
    update_iteration_number() const;

public:

    void
    clear();

    /**
     * @brief return the const reference to log_file_name
     * @return log_file_name
     */
    std::string
    get_log_file_name() const;

    std::string
    get_elapsed_time_info() const;

    /**
     * @brief build the class
     * read info from database that contains information in setup.dat file
     * @param db that contain a command read from file with the format of
     */
    void
    get_from_input (
        const InputDatabase* db);

    friend std::ostream&
    operator << (
        std::ostream& os,
        const CommonInfo& rhs);

    bool
    check_all_info_db(const InputDatabase* db);



private:

    typedef StateIndicator Parent;

    std::string
    get_restart_file_name (
        const std::string& restart_read_directory,
        const int restore_number) const;

    void
    set_restore_number_automatically (
        const std::string& restart_read_directory);

private:

    /*
     * the log file name
     */
    std::string d_proj_directory;

    /*
     * the base name used in the simulation. it is used for other object's name
     */
    std::string d_proj_name;

#if 0

    /*
     * tells how to do if there exists file with same name When writing files to the disk
     */
    WarningLevelType d_overwrite_exist_file_manner;

    /*
     * indicate whether log on all cpus
     */
    bool d_do_log_all_nodes;

    /*
     * used for debug.
     */
    bool d_do_performance_log;
#endif

    /*
     * the dimension of the probem, it should be 2 or 3,
     * dim = 0 means it has not been set yet.
     */
    int d_dim;

#if 0
    /*
     * Usually space_degree equal to dimension. Sometimes a 3D problem will has
     * a degree of 1 or 2, for example, a curve or surface in 3D space.
     */
    int d_space_degree;

    /*
     * Used in 2D problem.
     */
    bool d_is_axial_symmetry;

    /*
     * Used when is_axial_symmetry=TRUE. can be "X" or "Y"
     */
    Axis d_axis_of_symmetry;

    /*
     * The axis_of_symmetry only tells the direction of the axis,
     * use the offset_of_axis to locate it. For example, when axis_of_symmetry is the line x=-4,
     * then set axis to "Y" and offset_of_axis to "-4".
     */
    double d_offset_of_axis;

    /*
     * indicate whether do restart
     */
    bool d_do_from_restart;

    /*
     * the restart file save in the directory
     */
    std::string d_restart_read_directory;

    /*
     * restore num, used to get the restore file
     */
    int d_restore_number;

    /*
     * indicate whether do write restarti information
     */
    bool d_do_write_restart;

    /*
     * if true, only one file will be used to save restart information
     */
    bool d_save_single_restart_file;

    /*
     * write the restart information in this directory
     */
    std::string d_restart_write_directory;

    /*
     * used in time itarator, the interval to save the restart information
     */
    int d_restart_interval;

    /*
     * If the time steps greater than it, program will finished.
     * Default to 0, means not monitor on it.
     */
    int d_max_num_time_steps;

    /*
     * if true, output information while runing.
     * this is the global option, other place may turn this option
     * off locally.
     */
    int d_global_verbose_level;

    /*
     * when d_use_c_code_to_evaluate_function is true,
     * all functions will be build into a c code.
     * and complied into a dynamic file.
     * so that when evoluate, it can be called directly.
     * and expreval lib will not used.
     * it seems thia may speed the evoluate process.
     * but...
     */
    bool d_use_c_code_to_evaluate_function;
#endif

    /*
     * This parameter controls whether stop and exit or give a
     * approximate value to continue the program when numeric limits is reached.
     * for example, if compute exp(x), when x=-1.e400, the program will be error,
     * but one can set it to zero to continue. Default to TRUE.
     */
    bool d_stop_when_numeric_limits_reached;
#if 0
    /*
     * the max ghost width of all variable.
     * this value is decided by program, not by user.
     */
    int d_max_ghost_width;

    /*
     * when d_is_max_ghost_width_decided=true, d_max_ghost_width can't
     * be changed any more.
     * some variable such as RegionAttribute should be build after
     * d_max_ghost_width is decided. so use this flag to tells whether
     * it is a right time to build the variable.
     */
    bool d_is_max_ghost_width_decided;

    /*
     * the global iteration number start from 0 and increase 1 each step.
     */
    mutable int d_iteration_number;

    double d_start_clock_time;
    mutable double d_current_clock_time;
#endif

private:

    DISALLOW_COPY_AND_ASSIGN (CommonInfo);
};

}

#include "COMMON/info/CommonInfo.inl"

#endif
